feat(claw): add channel pairing step and load-settled gate to onboarding#1391
Merged
feat(claw): add channel pairing step and load-settled gate to onboarding#1391
Conversation
After provisioning completes, users who selected Telegram or Discord are shown an inline pairing step that polls for incoming pairing requests and lets them approve with a button. Slack skips this step since it has no dmPolicy/pairing mechanism. - New ChannelPairingStep component with channel-specific instructions - ClawDashboard captures selectedChannelId and routes to pairing step - ProvisioningStep accepts dynamic totalSteps (4 or 5)
Extract ChannelPairingStepView as a pure visual component (no hooks) following the ProvisioningStep/ProvisioningStepView pattern. Stories cover both channels, waiting/request/approving/loading states.
Replace instruction card + dashed polling box with a centered spinner, heading, and subtitle matching the provisioning step style. Title now reads 'Pair your Telegram/Discord bot'. Skip button uses subdued opacity. Step indicator stays left-aligned.
Show pairing code prominently with user ID, full-width authorize button, and decline link. Remove dead imports and JSX comments. Add cursor-pointer to all interactive elements.
…h-then-wait Replaces setInterval(5s) with a sequential loop that waits 1s after each fetch completes, preventing request pileup on slow responses.
Move the 60-second boot delay from ChannelPairingStep into ProvisioningStep so the user sees one continuous 'Setting up your instance' spinner instead of two spinners in sequence. Config mutations still fire immediately; onComplete is deferred until both the config is applied and the timer elapses. Fix the approval flash bug where the UI briefly reverted to the 'waiting for message' state after approving a pairing request. The mutation's global onSuccess invalidates the pairing query (clearing matchingRequest) before the call-site onSuccess fires onComplete. pendingApproval preserves the request data across that refetch window.
Expose the controller's /_kilo/health endpoint (bootstrapping → starting → ready → degraded) through the full stack so the frontend can track machine bootstrap progress. Both ProvisioningStep and ChannelPairingStep poll every 1s and log the result to the browser console.
Add /_kilo/gateway/ready controller route that fetches /ready from the OpenClaw gateway at 127.0.0.1:3001 and exposes it through the full stack. Both ProvisioningStep and ChannelPairingStep now poll both controller health (/_kilo/health) and gateway ready (/ready) every 1s, logging both to the browser console for comparison during onboarding.
Return 200 with error details in the body instead of 500 when the gateway isn't reachable yet. Prevents a wall of errors in the console and tRPC cache during the bootstrap window.
Wait for the gateway to report ready: true instead of an arbitrary 60s timeout. Remove console logging from both onboarding steps.
The controller health polling was only needed for debugging. The gateway /ready endpoint is the one used for the provisioning gate.
The /ready endpoint reports readiness before boot CPU pressure subsides. When the user sends a message immediately after ready: true, the combined load triggers throttling on the shared-cpu-2x instance. Add os.loadavg() and a 'settled' boolean to the controller's /ready response (threshold: 0.1 for ~6% shared CPU allocation), and gate ProvisioningStep on settled === true so the frontend waits for the system to actually be idle before advancing.
Contributor
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)WARNING
Other Observations (not in diff)N/A Files Reviewed (13 files)
|
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Reviewed by gpt-5.4-20260305 · 1,272,556 tokens |
pandemicsyn
approved these changes
Mar 24, 2026
# Conflicts: # src/app/(app)/claw/components/ProvisioningStep.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/readyendpoint through from controller → DO → tRPC → frontend to replace the hardcoded 60-second boot delay with real readiness pollingos.loadavg()[0] < 0.1) in addition to gateway readiness — the controller now returnsloadAverageandsettledfields in the/readyresponse, preventing the frontend from advancing before boot CPU pressure subsides on the shared-cpu-2x instanceVerification
pnpm typecheck— passespnpm format— passes (pre-push hook ran format:check + lint + typecheck)pnpm lint— passesVisual Changes
telegram-pairing.mp4
Reviewer Notes
kiloclaw/controller/src/routes/gateway.ts) requires a new Docker image deploy. Since this targets onboarding (new machines), they'll get the new image automatically.GatewayReadyResponseSchemais alreadyz.record(z.string(), z.unknown())— the newloadAverage/settledfields flow through without schema changes.LOAD_SETTLED_THRESHOLDof 0.1 is calibrated forshared-cpu-2x(~6% of 2 physical cores). An idle system sits near 0; this threshold ensures boot work has fully subsided.loadAverage/settled, so the frontend naturally won't advance when things are broken.